package com.loopj.ohos.http.sample;

import com.loopj.ohos.http.*;
import com.loopj.ohos.http.sample.util.API8Util;
import cz.msebera.android.httpclient.Header;
import cz.msebera.android.httpclient.HttpEntity;
import ohos.aafwk.content.Intent;
import ohos.agp.components.TextField;

import java.util.*;

/**
 * RequestParamsDebug
 */
public class RequestParamsDebug extends SampleParentAbility {
    /**
     * RequestParamsDebug
     */
    public static final String LOG_TAG = "RequestParamsDebug";
    private static final String DEMO_RP_CONTENT = "array=java" + " /// " +
            "array=C" + " /// " +
            "list=blue" + " /// " +
            "list=yellow" + " /// " +
            "set=music" + " /// " +
            "set=art" + " /// " +
            "map=first_name" + " /// " +
            "map=last_name";
    private TextField customParams;

    @Override
    public ResponseHandlerInterface getResponseHandler() {
        return new TextHttpResponseHandler() {

            @Override
            public void onFailure(int statusCode, Header[] headers, String responseString, Throwable throwable) {
                debugStatusCode(LOG_TAG, statusCode);
                debugHeaders(LOG_TAG, headers);
                debugResponse(LOG_TAG, responseString);
                debugThrowable(LOG_TAG, throwable);
            }

            @Override
            public void onSuccess(int statusCode, Header[] headers, String responseString) {
                debugStatusCode(LOG_TAG, statusCode);
                debugHeaders(LOG_TAG, headers);
                debugResponse(LOG_TAG, responseString);
            }
        };
    }

    @Override
    public void onStart(Intent intent) {
        super.onStart(intent);
        customParams = new TextField(this);
        customParams.setMaxTextLines(8);
        customParams.setText(DEMO_RP_CONTENT);
        customFieldsLayout.addComponent(customParams);
    }

    @Override
    public String getDefaultURL() {
        return PROTOCOL + "httpbin.org/get";
    }

    @Override
    public boolean isRequestHeadersAllowed() {
        return false;
    }

    @Override
    public boolean isRequestBodyAllowed() {
        return false;
    }

    @Override
    public int getSampleTitle() {
        return ResourceTable.String_title_request_params_debug;
    }

    @Override
    public RequestHandle executeSample(AsyncHttpClient client, String URL, Header[] headers, HttpEntity entity, ResponseHandlerInterface responseHandler) {
        return getAsyncHttpClient().get(this, getDefaultURL(), getRequestParams(), getResponseHandler());
    }

    // TODO: allow parsing multiple values for each type, maybe like "type.key=value" ?
    private RequestParams getRequestParams() {
        RequestParams rp = new RequestParams();
        String customParamsText = customParams.getText().toString();
        String[] pairs = customParamsText.split("\n");
        Map<String, Map<String, String>> mapOfMaps = new HashMap<>();
        Map<String, List<String>> mapOfLists = new HashMap<>();
        Map<String, String[]> mapOfArrays = new HashMap<>();
        Map<String, Set<String>> mapOfSets = new HashMap<>();
        for (String pair : pairs) {
            String[] kv = pair.split("=");
            if (kv.length != 2) {
                continue;
            }
            String key = kv[0].trim();
            String value = kv[1].trim();
            rowLimit(key, value, mapOfArrays, mapOfLists, mapOfSets, mapOfMaps);
        }
        for (Map.Entry<String, List<String>> entry : mapOfLists.entrySet()) {
            rp.put(entry.getKey(), entry.getValue());
        }
        for (Map.Entry<String, String[]> entry : mapOfArrays.entrySet()) {
            rp.put(entry.getKey(), entry.getValue());
        }
        for (Map.Entry<String, Set<String>> entry : mapOfSets.entrySet()) {
            rp.put(entry.getKey(), entry.getValue());
        }
        for (Map.Entry<String, Map<String, String>> entry : mapOfMaps.entrySet()) {
            rp.put(entry.getKey(), entry.getValue());
        }
        debugResponse(LOG_TAG, rp.toString());
        return rp;
    }

    private void rowLimit(String key, String value, Map<String, String[]> mapOfArrays, Map<String, List<String>> mapOfLists, Map<String, Set<String>> mapOfSets, Map<String, Map<String, String>> mapOfMaps) {
        if ("array".equals(key)) {
            String[] values = mapOfArrays.get(key);
            if (values == null) {
                values = new String[]{value};
            } else {
                values = API8Util.copyOfRange(values, 0, values.length + 1);
                values[values.length - 1] = value;
            }
            mapOfArrays.put(key, values);
        } else if ("list".equals(key)) {
            List<String> values = mapOfLists.get(key);
            if (values == null) {
                values = new ArrayList<>();
            }
            values.add(value);
            mapOfLists.put(key, values);
        } else if ("set".equals(key)) {
            Set<String> values = mapOfSets.get(key);
            if (values == null) {
                values = new HashSet<>();
            }
            values.add(value);
            mapOfSets.put(key, values);
        } else if ("map".equals(key)) {
            Map<String, String> values = mapOfMaps.get(key);
            if (values == null) {
                values = new HashMap<>();
            }
            values.put(key + values.size(), value);
            mapOfMaps.put(key, values);
        }
    }
}
